/*  tBookShelf: HyphenationManager
    (C) 2007  TvN (Volodymyr Tarasenko), e-mail: tvntsr@yahoo.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iostream>

#include <algorithm>
#include <stdexcept>
#include "Utils/HyphenationManager.hpp"

using namespace std;

int HyphenationManager::hyphenateString(std::string& str, 
                                        std::string& rest,
                                        size_t       max_len)
{
    if (0 == mCurr)
        throw std::runtime_error("Hyphenation dictionary is not selected");
    // find the last word
    size_t wstart = str.rfind(' ', max_len);
    if (wstart == max_len)
    {
        rest = str.substr(max_len);
        str.erase(max_len);
        return 0;
    }

    size_t wend = str.find(' ', max_len);

    string word = str.substr(wstart, wend);
    int ret = hyphenateWord(word, rest, max_len - wstart);
    if (ret == 0)
    {
        rest += str.substr(wend);

        str.erase(wstart);
        str+= word;
    }

    return ret;
}

size_t HyphenationManager::hyphenateString(const std::string& str, 
                                           const size_t       max_len)
{
    if (0 == mCurr)
        throw std::runtime_error("Hyphenation dictionary is not selected");

    if (str[max_len] == ' ')
        return max_len;

    // find the last word
    size_t wstart = str.rfind(' ', max_len);
    if (wstart == string::npos)
    {
        wstart = 0;
    }

    size_t wend = str.find(' ', max_len);

    string word = str.substr(wstart+1, wend - wstart - 1);

    cerr << "Word is [" << word << "]" << endl;

    string rest;

    size_t pos = wstart;

    try{
        int ret = hyphenateWord(word, rest, max_len - wstart);
        if (ret == 0)
        {
            cerr << "Word [" << word << "], Rest:" << rest 
                 << ", word size is " << word.size()
                 << endl;
            pos = word.size() > 1 ? wstart + word.size(): wstart;
            cerr << "Symbol at pos is ["
                 << str[pos]
                 << "]"
                 << endl;
        }
    }catch(exception& err)
    {
        cerr << "Error:"
             << err.what()
             << endl;
    }

    return pos;
}


struct findDict{
    const std::string & enc;
    
    findDict(const std::string & e)
        : enc(e)
    {}

    bool operator()(const HyphenDict* item)
    {
        return item->dictCharset() == enc;
    }
};


void HyphenationManager::selectDict(const std::string& enc_name)
{
    HyphenDictList::iterator p = find_if(mDicts.begin(), mDicts.end(), 
                                         findDict(enc_name));

    if (p == mDicts.end())
    {
        throw std::runtime_error("Hyphenation dictionary is not found");
    }

    mCurr = *p;
}


int HyphenationManager::hyphenateWord(std::string& str, 
                                      std::string &rest, 
                                      size_t max_len)
{
    if (0 == mCurr)
        throw std::runtime_error("Hyphenation dictionary is not selected");

    int n = str.size()-1;
    while((n >=0) && (str[n] == '.')) n--;
    n++;

    str.erase(n);

    string hyphens;
    cerr << "word to hyphenate ["
         << str
         << "]"
         << endl;

    mCurr->hyphenate(str, hyphens);

    cerr << "res:" << hyphens << endl;

    string hyphword;
    int pos = 0;
    for (int i = 0; i < n; i++) {
        hyphword += str[i];
        if (hyphens[i]&1)
        {
            pos = i;
        }
        if (hyphword.size()>= max_len)
        {
            hyphword[pos] = '-';
            hyphword.erase(pos+1);
            rest = str.substr(pos);
            str = hyphword;
            return 0;
        }
    }

    return -1; // Not finished yet

}
